package com.example.ccj.b.c.draw;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


import com.example.ccj.u.ImageUtils;
import com.example.ccj.u.LogUtils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 手写签名 主要功能
 * 主要功能：绘制，撤销、清除、颜色、背景、宽度设置，导出文件，导入文件
 * 驰郡
 * wechat:chijun9
 * 2023/11/27
*/
public class SignatureView extends View {
    private Path path; // 用于绘制路径
    private Paint paint; // 用于绘制画笔
    private ArrayList<Path> paths = new ArrayList<>(); // 保存所有路径
    private ArrayList<Paint> paints = new ArrayList<>(); // 保存所有画笔
    private int currentColor = Color.BLACK; // 当前画笔颜色
    private int currentWidth = 5; // 当前画笔宽度
    private Stack<Path> rePath = new Stack<>();
    private Stack<Paint> rePaint = new Stack<>();
    // 定义橡皮擦模式
    private boolean eraseMode = false;
    private List<Bitmap> oldBitMap = new ArrayList<>();


    public SignatureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        path = new Path();
        paint = new Paint();
        //设置画笔是否启用抗锯齿效果 用于减少图形边缘的锯齿状失真，使得图形边缘更加平滑
        paint.setAntiAlias(true);
        //设置画笔抖动效果 可以在颜色深度较低的设备上模拟更多的颜色
        paint.setDither(true);
        paint.setColor(currentColor);
        //设置画笔绘制模式 FILL（填充）、STROKE（描边）和FILL_AND_STROKE（填充和描边）。
        paint.setStyle(Paint.Style.STROKE);
        //设置画笔线段连接处样式 MITER（结合处为锐角）、ROUND（结合处为圆弧）和 BEVEL（结合处为直线）
        paint.setStrokeJoin(Paint.Join.ROUND);
        //画笔的线帽指的是线条的两端的样式，可以是BUTT（无线帽）、ROUND（圆线帽）或SQUARE（方线帽）。
        paint.setStrokeCap(Paint.Cap.ROUND);
        //设置画笔绘制线条的宽度 以像素为单位的，默认值是 0
        paint.setStrokeWidth(currentWidth);
//        setSignatureBackgroundColor(mBackgroundColor);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < paths.size(); i++) {
            canvas.drawPath(paths.get(i), paints.get(i));
        }
        canvas.drawPath(path, paint);
    }

    float startX;
    float startY;
    float endX;
    float endY;

    int maxX = 0;
    int minX = 1000;
    int maxY = 0;
    int minY = 1000;
    int paintMaxWidth = 5;//画笔最大宽度

    /**
     * 获取最合适的截图范围
     * @param x 当前绘制的x坐标
     * @param y 当前绘制的y坐标
     */
    private void getScreenshotRange(float x,float y){
        if (x>maxX) maxX = (int)x;
        if (x<minX) minX = (int)x;
        if (y>maxY) maxY = (int)y;
        if (y<minY) minY = (int)y;
    }


    boolean isDrawCurrent = true;
    boolean isUp = true;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();//按下时的x，y坐标
                getScreenshotRange(startX,startY);
//                logUtil.d("按下x:"+startX+"--y:"+startY);

                isDrawCurrent = true;
                // 当手指按下时，创建一个新的路径并将其移动到触摸点,将当前路径和画笔添加到列表中，并创建新的路径和画笔
//                path.reset(); // 重置路径
                path = new Path(); // 创建新的路径
                paint = new Paint(); // 创建新的画笔

                //设置画笔是否启用抗锯齿效果 用于减少图形边缘的锯齿状失真，使得图形边缘更加平滑
                paint.setAntiAlias(true);
                //设置画笔抖动效果 可以在颜色深度较低的设备上模拟更多的颜色
                paint.setDither(true);

                if (eraseMode) paint.setColor(Color.TRANSPARENT);
                else paint.setColor(currentColor);

                //设置画笔绘制模式 FILL（填充）、STROKE（描边）和FILL_AND_STROKE（填充和描边）。
                paint.setStyle(Paint.Style.STROKE);
                //设置画笔线段连接处样式 MITER（结合处为锐角）、ROUND（结合处为圆弧）和 BEVEL（结合处为直线）
                paint.setStrokeJoin(Paint.Join.ROUND);
                //画笔的线帽指的是线条的两端的样式，可以是BUTT（无线帽）、ROUND（圆线帽）或SQUARE（方线帽）。
                paint.setStrokeCap(Paint.Cap.ROUND);
                //设置画笔绘制线条的宽度 以像素为单位的，默认值是 0
                paint.setStrokeWidth(currentWidth);
                path.moveTo(x, y); // 将路径移动到触摸点

                break;
            case MotionEvent.ACTION_MOVE:
                endX = event.getX();
                endY = event.getY();
//                logUtil.d("移动x:"+endX+"--y:"+endY);
                getScreenshotRange(endX,endY);
                path.quadTo(startX, startY, endX, endY);//二阶贝济埃曲线，更加光滑
                startX = endX;
                startY = endY;
                break;
            case MotionEvent.ACTION_UP:
                paths.add(path); // 将当前路径添加到路径列表中
                paints.add(paint); // 将当前画笔添加到画笔列表中
//                logUtil.d("结束x:"+maxX+"--y:"+minX+"--y:"+maxY+"--"+minY);
                break;

            default:
                return false;
        }

        invalidate(); // 请求重绘视图
        return true;
    }

    public void toggleEraseMode(){
        eraseMode = !eraseMode;
    }

    /**
     * 清除签名
     */
    public void clear() {
        paths.clear();
        paints.clear();
        path.reset();
        paint.reset();
        oldBitMap.clear();
        invalidate();
    }

    /**
     * 撤销上一步操作
     */
    public void undo() {
        if (oldBitMap.size() > 0) {
            isDrawCurrent = false;

            rePath.push(paths.get(paths.size()-1));
            rePaint.push(paints.get(paints.size()-1));
            paths.remove(paths.size() - 1);
            paints.remove(paints.size() - 1);
            //回调返回撤销的步数
            if (onSignatureCompletedListener != null) onSignatureCompletedListener.onUndo(oldBitMap.size());
            invalidate();//重绘
        }
    }

    /**
     * 重做上一步撤销的操作
     */
    public void redo() {
        if (paths.size() > 0) {
            isDrawCurrent = false;
            paths.add(rePath.pop());
            paints.add(rePaint.pop());
            //回调返回剩余可重做步数
            if (onSignatureCompletedListener != null) onSignatureCompletedListener.onRedo(paths.size());
            invalidate();//重绘
        }
    }

    /**
     * 设置画笔颜色
     * @param color 画笔颜色
     */
    public void setColor(int color) {
        currentColor = color;
    }

    /**
     * 验证线宽是否有效
     * @param width 线宽值
     * @return 如果线宽有效则返回true，否则返回false
     */
    private boolean isValidWidth(float width) {
        return width > 0;
    }

    /**
     * 设置画笔宽度
     * @param width 画笔宽度
     */
    public void setWidth(float width) {
        LogUtils.d("设置画笔宽度" + width);
        if (!isValidWidth(width)) {
            // 可以在这里添加错误处理逻辑，例如打印错误日志或抛出异常等
            return;
        }
        currentWidth = (int) width;
        if (currentWidth > paintMaxWidth) paintMaxWidth = currentWidth;
    }

    int mBackgroundColor = Color.WHITE;

    /**
     * 改变签名的背景颜色
     * @param color 颜色
     */
    public void setSignatureBackgroundColor(int color) {
        this.mBackgroundColor = color;
//        setBackgroundColor(color);
//        invalidate(); // 更新视图以显示新的背景颜色设置效果
    }

    /**
     * 获取签名位图
     * @return 签名位图
     */
    public Bitmap getSignatureBitmap() {
//        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
//        Canvas canvas = new Canvas(bitmap);
//        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
//        draw(canvas);

        Bitmap bitmap = ImageUtils.loadBitmapFromView(this,Color.WHITE);
        //截取绘制范围内的
        Bitmap bitmap1 = Bitmap.createBitmap(bitmap,minX- paintMaxWidth -5,minY- paintMaxWidth -5,maxX-minX+ paintMaxWidth +5,maxY-minY+ paintMaxWidth +5);

        return bitmap1;
    }

    /**
     * 设置签名位图
     * @param bitmap 签名位图
     */
    public void setSignatureBitmap(Bitmap bitmap) {
        clear();
        Paint newPaint = new Paint();
        newPaint.setAntiAlias(true);
        newPaint.setDither(true);
        newPaint.setColor(currentColor);
        newPaint.setStyle(Paint.Style.STROKE);
        newPaint.setStrokeJoin(Paint.Join.ROUND);
        newPaint.setStrokeCap(Paint.Cap.ROUND);
        newPaint.setStrokeWidth(currentWidth);
        paths.add(new Path());
        paints.add(newPaint);
        paths.get(0).addPath(path);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
        draw(canvas);
        invalidate();
    }

    /**
     * 保存签名位图到文件
     * @param filename 文件名
     * @return 是否保存成功
     */
    public boolean saveSignatureToFile(String filename) {
        Bitmap bitmap = getSignatureBitmap();
        try {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(filename));
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 从文件加载签名位图
     * @param filename 文件名
     * @return 是否加载成功
     */
    public boolean loadSignatureFromFile(String filename) {
        Bitmap bitmap = BitmapFactory.decodeFile(filename);
        if (bitmap != null) {
            setSignatureBitmap(bitmap);
            return true;
        } else {
            return false;
        }
    }

    OnSignatureCompletedListener onSignatureCompletedListener;

    public void setOnSignatureCompletedListener(OnSignatureCompletedListener onSignatureCompletedListener) {
        this.onSignatureCompletedListener = onSignatureCompletedListener;
    }

    public interface OnSignatureCompletedListener{
        void onUndo(int num);
        void onRedo(int num);
    }


    public boolean isEraseMode() {
        return eraseMode;
    }

    public void setEraseMode(boolean eraseMode) {
        this.eraseMode = eraseMode;
    }
}